/*
 * worker.c
 *
 *  Created on: May 6, 2009
 *      Author: marco
 */
//#include "/home/marco/workspace/np/np.h"
#include "nmat.h"
#include <stdio.h>  /* serve per la perror */
#include <stdlib.h> /* serve per la exit   */
#include <string.h> /* serve per strlen    */
#include <errno.h>  /* serve per errno     */
#include <unistd.h> /* serve per la write  */
#include <ctype.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

#define FILES 4; // ?

/*
 * per quanto riguarda la o_pipe..
 * 		-o si crea qui quando è autenticato e si crea in nmats per comunicare fallimento
 * 		-o si crea comunque in nmats
 */
void run();
void msgprint(msg);
int receive(msg*, int);
msg* compute(msg* m);
// funzioni/comandi
int new(); // tutti sti int?
int print();
int list();
int save();
int load();
int clientexit();
int help(); //magari basta nel client?
int TRASP();

char **matrices;
char buffer[121];
char *cmdline = NULL; // non serve?
char **args; // ma portarlo dentro la funz?
int mnum = 0;
int allocated = 10; //nome migliore?
int arg_num = 5; //macro?

int in;
int out;

volatile int cpid;
volatile char *asd; //ok , ma modo migliore?
void term_handler(int);


//GESTIRE SIGPIPE!!!!!!!

//sopratutto.. modo migliore di passare parametri che per argomenti così?
int main(int argc, char **argv) { //serve argc?

	struct sigaction term_action;
	bzero(&term_action, sizeof(term_action));
	term_action.sa_handler = term_handler;
	sigaction(SIGTERM,&term_action,NULL);

	struct sigaction int_action; // si ignora altrimenti la sigint su nmat uccide tutto in foreground
	bzero(&int_action, sizeof(int_action));
	int_action.sa_handler = SIG_IGN;
	sigaction(SIGINT,&int_action,NULL);


	int pid = getpid();

	char *i_pipe;
	char *o_pipe;
	//char *buffer;
	i_pipe = malloc(30 * sizeof(char));
	o_pipe = malloc(30 * sizeof(char));
	DIR *wdir;
	struct dirent *file;

	cpid = atoi(argv[2]);
	printf("CPID è %d\n",cpid);

	printf("Worker %d per l'utente %s:%s\n",pid,argv[1],argv[2]);
	sprintf(i_pipe,"%s%s","../clientserver",argv[2]); //giusto dare cosi la dir?

	//pattume da togliere
	asd = malloc ( (strlen(i_pipe)+ 3) * sizeof(char) );
	sprintf((char*)asd, "%s%s", "../", i_pipe);
	char *antani;
	antani = malloc(30 *sizeof(char));
	sprintf(antani, "%s%s", "clientserver", argv[2]);
	//fine pattume


	mkfifo(i_pipe, 0666); //magari farle fare tutte in /tmp
	in = open(i_pipe, O_RDWR); // riguardarsi i nonblock
	printf("IN=%d\n",in);
	printf("creata la pipe %s\n",i_pipe);
	sprintf(o_pipe,"%s%s","../serverclient",argv[2]);
	out = open(o_pipe, O_WRONLY);
	printf("Worker:out è %d\n",out);
	perror("worker:open di out");
	//magari farle fare tutte in /tmp
	printf("Worker: pipe pronte\n");

//	if (chdir(argv[1]) == -1) { //farne na macruccia?
//		perror("chdir");
//		exit(errno);
//	}
	char *temp;
	char *aux;
	char *aux2;

	//questo pezzo da risistemare per lo warning
	temp = malloc(80 * sizeof(char));
	aux = malloc(80 * sizeof(char));
	aux = getwd(aux); // e questo uorning? //dice dangerous..
	perror("getwd(aux)");
	aux2 = malloc(80 * sizeof(char));
	//aux2 = getwd(aux2);
	//perror("getwd(aux2)");
	sprintf(temp,"%s/%s",".",argv[1]);
	printf("temp = !%s! \n", temp);

	if ((wdir = opendir (temp)) == NULL ) {
		perror("errore opendir");
		exit(errno);
	}
	chdir(temp);
	perror("chdir");
//	aux2 = getcwd(aux2, 30);
//	perror("getcwd(aux2, 30)");
	aux2 = getwd(aux2);
	perror("getwd(aux2)");

	printf("aux=%s aux2=%s", aux, aux2);
	matrices = malloc(allocated * sizeof(char*)); //cambiare in mat_names?

	//problema.. cosi quelle create dopo saltanol'ordine?

	while((file=readdir(wdir))) { // ma cosi mette anche . e ..

		if (mnum == allocated) {
			allocated *= 2;//meglio?
			matrices = realloc(matrices, allocated * sizeof(char*)); //non va o si?
		}
		// per if(S_ISREG(file->d_type)) rivedere.. da usare stat..
		if(file->d_type == DT_REG){ //if(file->d_type == 8)
			printf("if dtype= %d\n",file->d_type);
			matrices[mnum] = file->d_name; // o strdup ??
			printf("%s\n",matrices[mnum]);
			mnum++;
		}


	 }// fine scansione dir

	printf("trovate %d matrici\n", mnum);
	 //controllare la directory
	printf("dir worker %s \n",get_current_dir_name());

	// fine controllo dir

	//sleep(2);

	printf("inizio lettura da pipe per comando\n");
//	while(!feof(in) && !ferror(in) && fgets(buffer, sizeof(buffer),in)) {
//		printf("!&s!", buffer);
//	}
	//RECEIVE
	int go = 1;
	msg cmd_msg; //dentro o fuori while?

	do {
		printf("Worker:inizio do-while\n");
		//DILEMMA msg cmd_msg //dentro o fuori while?

		receive(&cmd_msg, in);
		msgprint(cmd_msg); // magari riadattarlo come controllo di debug

		//switchone sul codice?
		//o inventarsi un puntatore a funz?

		//if temporaneo per testare la lista

		if(cmd_msg.cmdcode == _list) {
			list();
		}


		go = cmd_msg.cmdcode;
		printf("GO=%d\n", go);
		// switch sul cmd_msg->cmdcode ?
		//free(cmd_msg);
	} while(cmd_msg.cmdcode); //e se è null? fare uin modo di avere consistente questo controllo


	printf("worker per %s in chiusura..\n", argv[1]);
	//uguale in sigterm...
	close(in);

	asd = malloc ( (strlen(i_pipe)+ 3) * sizeof(char) );
	sprintf(asd, "%s%s", "../", i_pipe);
	unlink(asd);
	perror("unlink i_pipe");
	exit(0);//fare macro per ok etc
}//fine main

//AAA SE SI BLOCCA IL SERVER E POI SEND poi si incatagna dopo il client

// new receive
int receive(msg *m, int ch) { //meglio che lo restituisca il messaggio?
	int rd; //farne un uso??
	int len;
	int i;
	int tmp;

	rd = read(ch,&(m->cmdcode),sizeof(int));
	rd += read(ch, &(m->argnum), sizeof(int));
	rd += read(ch, &(m->nnum), sizeof(int));

	//lettura args
	if (m->argnum) {
		printf("dentro argnum\n");
		m->args = malloc(m->argnum * sizeof(char*));
		perror("malloc m->args");
		for (i = 0; i < m->argnum; i ++) {
			rd += read(ch,&len,sizeof(int));
			m->args[i] = malloc(len * sizeof(char *));
			rd += read(ch, m->args[i], len);
			perror("read arg");
		}
	}
	//lettura numeri
	if (m->nnum) {  // ma cmq ci sarà un modo più diretto?
		printf("dentro nnum\n");
		m->numbers = malloc(m->nnum*sizeof(int));
		perror("malloc numbers");
		for(i = 0; i < m->nnum; i++) {
			rd += read(ch,&tmp, sizeof(int));
			m->numbers[i] = tmp;
			perror("read num");
		}

	}
	printf("receive ha ricevuto %d bytes\n", rd);
	return 1; //tanto per
}

//passiamolo per valore o per rif?
void msgprint(msg m) { //fare una print generica in un util.h o print.h !!!
	int i;
	printf("MSGPRINT:\n");
	if(&m != NULL) {
		printf("cmd = %d || argnum = %d || nnum = %d\n",m.cmdcode,m.argnum,m.nnum);
		if(m.argnum) {
			i = m.argnum;
			for (i = 0;i < m.argnum; i ++){
				printf("arg[%d]=%s\n",i,m.args[i]);
			}
		}
		if(m.nnum) {
			i = m.nnum;
			for (i = 0;i < m.nnum; i ++){
				printf("num[%d]=%d\n",i,m.numbers[i]);
			}
		}


	}

}//fine msgprint


//fare .h / .c per i comandi a parte?
int list() {
	int len;
	int i;
	printf("LIST!\n");
	write(out,&mnum,sizeof(int));
	//while (matrices[i] != NULL) {
	for(i = 0; i< mnum; i++){
		printf("%s\n",matrices[i]);
		len = strlen(matrices[i]);
		write(out,&len,sizeof(int));
		write(out,matrices[i],len);
		}
	return 1;
}

void term_handler(int signum) {
	printf("sighandler WORKEEEER\n");
	kill((pid_t)cpid, SIGTERM);
	close(in);
	//char *asd; //ok , ma modo migliore?
	//asd = malloc ( (strlen(i_pipe)+ 3) * sizeof(char) );
	//sprintf(asd, "%s%s", "../", i_pipe);
	unlink(asd);
	perror("unlink i_pipe");
	printf("exit da termhandler\n");
	exit(0);
}
